#pragma once

#include <mysql/mysql.h>
#include <jsoncpp/json/json.h>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
#include <sstream>
#include <string>
#include "log.hpp"

typedef websocketpp::server<websocketpp::config::asio> websocket_server;


// 实现基础的工具:
// 1. 对Mysql数据库接口进行封装 ;
// 2. 封装Json序列化和反序列化 ;
// 3. 分割字符串操作
// 4. 读取文件操作




// 1. 对Mysql数据库接口进行封装mysql_util
// 1.1 初始化: 连接服务器 , 设置数据库编码集 , 打开数据库
// 1.2 先数据库发送指令进行操作
// 1.3 销毁数据库

class Mysql_util
{
public:
    
    static MYSQL* init(const std::string &host, const std::string &user, const std::string &passwd,
              const std::string &db, uint16_t port)
    {
        MYSQL* _mysql = mysql_init(nullptr);

        // 1. 连接服务器
        if(mysql_real_connect(_mysql , host.c_str() , user.c_str() , passwd.c_str() , db.c_str() ,port , nullptr , 0) == nullptr)
        {
            Log_ns::Log(Log_ns::Fatal) << "mysql connect failed !!!";
            return nullptr;
        }
        // 2. 设置字符集
        if(mysql_set_character_set(_mysql , "utf8") != 0)
        {
            Log_ns::Log(Log_ns::Error) << "mysql set character failed !!!";
            return nullptr;
        }
        return _mysql;
    }

    static bool exec(MYSQL* mysql , const std::string& command)
    {
        if(mysql_query(mysql , command.c_str()) != 0)
        {
            Log_ns::Log(Log_ns::Warning) << "mysql query failed , the command is " << command;
            return false;
        }
        return true;
    }

    static void destory(MYSQL* mysql)
    {
        mysql_close(mysql);
    }

private:
};



// 2. 构建序列化和反序列化工具json_util
// 2.1 给Json::Value进行序列化
// 2.2 给string进行反序列化得到Json::Value

class Json_util
{
public:
    static bool serialization(const Json::Value &value , std::string& str)
    {
        Json::StreamWriterBuilder swbulider;
        std::shared_ptr<Json::StreamWriter> sw(swbulider.newStreamWriter());

        std::stringstream ss;
        sw->write(value , &ss);
        str = ss.str();
        return true;
    }

    static bool unserialization(const std::string & str , Json::Value & value)
    {
        Json::CharReaderBuilder crbuilder;
        std::shared_ptr<Json::CharReader> cr(crbuilder.newCharReader());

        Json::String err;
        if(!cr->parse(str.c_str() , str.c_str() + str.size() , &value , &err))
        {
            Log_ns::Log(Log_ns::Warning) << "unserialization failed , " << err;
            return false;
        }
        return true;
    }
private:
};


// 3. 进行字符串分割

class String_util
{
public:
    static int spilt(const std::string& src , const std::string& sep , std::vector<std::string> &res)
    {
        res.clear();
        size_t start = 0 , n = src.size();
        while(start < n)
        {
            size_t pos = src.find(sep , start);
            if(pos == std::string::npos)
            {
                res.push_back(src.substr(start));
                break;
            }
            if(pos - start > 0)
                res.push_back(src.substr(start , pos - start));
            start = pos + 1;
        }
        return res.size();
    }
};


// 4. 读取文件
class File_util
{
public:
    static bool readfile(const std::string& file_name , std::string& content)
    {
        std::ifstream ifs(file_name , std::ios::binary);
        if(!ifs.is_open())
        {
            return false;
        }
        ifs.seekg(0 ,std::ios::end);
        size_t fsize = ifs.tellg();
        content.resize(fsize);
        ifs.seekg(0, std::ios::beg);    
        ifs.read(&(content[0]) , fsize);
        return true;
    }
};